using System;
using System.IO;
using System.Xml;
using System.Xml.XPath;

namespace VCDepend.Engine
{
	public class VcProjParser : IProjectParser
	{
    public Project ParseProject(string projectId, string path, string configuration)
		{
			XmlDocument document = LoadDocumentFromFile(path);

      string projectName = GetAttributeValue(document, "//VisualStudioProject/@Name");
			string outputName = GetOutputName(document, configuration);

			Project project = new Project(projectId, projectName, path, outputName);

			AddLinkDependencies(project, document, configuration);

			return project;
		}

		private XmlDocument LoadDocumentFromFile(string filename)
		{
			XmlDocument document = new XmlDocument();
			document.Load(filename);

			return document;
		}

		private string GetOutputName(XmlDocument document, string configuration)
		{
      string xpath = BuildLinkerSettingXPath(configuration, "ImportLibrary");

      string linkerOutput = GetAttributeValue(document, xpath);
      if (!string.IsNullOrEmpty(linkerOutput))
        linkerOutput = Path.GetFileName(linkerOutput);

      return linkerOutput;
		}

		private void AddLinkDependencies(Project project, XmlDocument document, string configuration)
		{
			string xpath = BuildLinkerSettingXPath(configuration, "AdditionalDependencies");

      string additionalDependencies = GetAttributeValue(document, xpath);

			string[] linkDependencies = additionalDependencies.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
			foreach (string dependency in linkDependencies)
			{
				project.AddLinkDependency(Path.GetFileName(dependency));
			}
		}

		private string BuildLinkerSettingXPath(string configuration, string setting)
		{
			return ("//VisualStudioProject/Configurations/Configuration[@Name='" + configuration + "']/Tool[@Name='VCLinkerTool']/@" + setting);
		}

    private string GetAttributeValue(XmlDocument document, string xpath)
    {
      XmlNode attributeNode = document.SelectSingleNode(xpath);
      if (attributeNode == null)
        return string.Empty;

      return attributeNode.Value;
    }
	}
}
